package no.nordicsemi.android.nrfmesh.node;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.util.Log;
import android.view.View;
import android.widget.*;
import android.widget.Toast;
import no.nordicsemi.android.nrfmesh.domain.DeviceStatus;



import com.google.android.material.textfield.TextInputLayout;

import com.google.gson.Gson;
import dagger.hilt.android.AndroidEntryPoint;
import no.nordicsemi.android.mesh.ApplicationKey;
import no.nordicsemi.android.mesh.models.VendorModel;
import no.nordicsemi.android.mesh.transport.ConfigVendorModelAppList;
import no.nordicsemi.android.mesh.transport.ConfigVendorModelSubscriptionList;
import no.nordicsemi.android.mesh.transport.Element;
import no.nordicsemi.android.mesh.transport.MeshMessage;
import no.nordicsemi.android.mesh.transport.MeshModel;
import no.nordicsemi.android.mesh.transport.VendorModelMessageAcked;
import no.nordicsemi.android.mesh.transport.VendorModelMessageStatus;
import no.nordicsemi.android.mesh.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmesh.R;
import no.nordicsemi.android.nrfmesh.domain.VendorModelData;
import no.nordicsemi.android.nrfmesh.domain.Wave;
import no.nordicsemi.android.nrfmesh.utils.HexKeyListener;
import no.nordicsemi.android.nrfmesh.utils.Utils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.view.ViewGroup;
import no.nordicsemi.android.nrfmesh.widgets.CustomControlsActivity;


@AndroidEntryPoint
public class VendorModelActivity extends ModelConfigurationActivity {
    private LinearLayout waveFormContainer;
    private EditText opCodeEdit;
    private final int MAX_WAVES = 3;
    private final List<View> waveViews = new ArrayList<>();

    private TextView tvOnOff, tvVoltage0, tvVoltage1, tvCurrent, tvResistance, tvSoc, tvGear;

    private View receivedMessageContainer;
    private TextView receivedMessageView;

    // 定义一个成员变量来存储 C1 数据
    private String latestC1Data = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 将 layout_vendor_model_controls 加入到父布局中，而不是 setContentView 替换整个界面
        ViewGroup container = findViewById(R.id.node_controls_container);
        View vendorControls = getLayoutInflater().inflate(R.layout.layout_vendor_model_controls, container, false);
        container.addView(vendorControls);

        waveFormContainer = vendorControls.findViewById(R.id.wave_form_container);
        opCodeEdit = vendorControls.findViewById(R.id.op_code);

        // Received message views
        receivedMessageContainer = vendorControls.findViewById(R.id.received_message_container);
        receivedMessageView = vendorControls.findViewById(R.id.received_message);

        Button addBtn = vendorControls.findViewById(R.id.add_wave_btn);
        Button sendBtn = vendorControls.findViewById(R.id.send_btn);
        Button skipBtn = vendorControls.findViewById(R.id.skip_btn);

        TextView tvOnOff = findViewById(R.id.tvOnOff);
        TextView tvVoltage0 = findViewById(R.id.tvVoltage0);
        TextView tvVoltage1 = findViewById(R.id.tvVoltage1);
        TextView tvCurrent = findViewById(R.id.tvCurrent);
        TextView tvResistance = findViewById(R.id.tvResistance);
        TextView tvSoc = findViewById(R.id.tvSoc);
        TextView tvGear = findViewById(R.id.tvGear);



        addBtn.setOnClickListener(v -> {
            if (waveViews.size() >= MAX_WAVES) {
                Toast.makeText(this, "最多添加 3 个 Wave", Toast.LENGTH_SHORT).show();
                return;
            }
            addWaveForm();
        });
        skipBtn.setOnClickListener(v -> {
            // 1、opCode
            String opCode = opCodeEdit.getText().toString().trim();
            if (TextUtils.isEmpty(opCode)) {
                Toast.makeText(this, "请填写 OpCode", Toast.LENGTH_SHORT).show();
                return;
            }
            // 2. 跳转到 CustomControlsActivity，并传递 opCode
            Intent intent = new Intent(this, CustomControlsActivity.class);
            intent.putExtra("EXTRA_OPCODE", opCode);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);   // ★ 关键
            Log.d("VendorModelActivity", "Launching CustomControlsActivity");

            startActivity(intent);

        });


        sendBtn.setOnClickListener(v -> {
            // 1、opCode
            String opCode = opCodeEdit.getText().toString().trim();
            if (TextUtils.isEmpty(opCode)) {
                Toast.makeText(this, "请填写 OpCode", Toast.LENGTH_SHORT).show();
                return;
            }

            // 1、波形数据
            List<Wave> waves = new ArrayList<>();
            for (View waveView : waveViews) {
                Wave wave = extractWave(waveView);
                if (wave == null) return;
                waves.add(wave);
            }

            VendorModelData data = new VendorModelData();
            data.setWaves(waves);

            String json = new Gson().toJson(data);
            Log.d("VendorSend", "opcode: " + opCode + ", payload: " + json);

            byte[] payload = json.getBytes(StandardCharsets.UTF_8);
            // 3、send
            sendVendorModelMessage(Integer.decode(opCode), payload, true);
        });
    }

    private void addWaveForm() {
        View form = getLayoutInflater().inflate(R.layout.item_wave_form, waveFormContainer, false);
        waveViews.add(form);
        waveFormContainer.addView(form);

        // 初始化 Spinner 的选项
        Spinner typeSpinner = form.findViewById(R.id.input_type);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this,
                R.array.wave_type_options,
                android.R.layout.simple_spinner_item
        );
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        typeSpinner.setAdapter(adapter);

        // 设置删除按钮的点击事件 -> 删除整个表单
        ImageButton closeBtn = form.findViewById(R.id.btn_close);
        if (closeBtn != null) {
            closeBtn.setOnClickListener(v -> {
                waveFormContainer.removeView(form);
                waveViews.remove(form);
            });
        }
    }

    private Wave extractWave(View form) {
        Wave wave = new Wave();
        try {
            wave.setCount(getText(form, R.id.input_steps));
//            wave.setRepeat(getText(form, R.id.input_repeat));
            wave.setTime(getText(form, R.id.input_time));
            wave.setGear(getText(form, R.id.input_gear));

            // Spinner 获取方式
            Spinner spinner = form.findViewById(R.id.input_type);
            int pos = spinner.getSelectedItemPosition();
            String code = pos >= 0 ? String.valueOf(pos + 1) : "0";
            // 记录日志便于排查
            Log.d("VendorModelActivity", "Selected wave label=" + spinner.getSelectedItem() + ", pos=" + pos + ", code=" + code);
            wave.setType(code);

            wave.setPusle_witdth(getText(form, R.id.input_pulse_width));
            wave.setFrequence(getText(form, R.id.input_frequence));
//            wave.setCount(getText(form, R.id.input_count));
            return wave;
        } catch (Exception e) {
            Toast.makeText(this, "请填写完整的 Wave 表单", Toast.LENGTH_SHORT).show();
            return null;
        }
    }

    private String mapWaveTypeToValue(String label) {
        // 兼容：优先解析括号中的编号，例如 "... (7)" → "7"
        java.util.regex.Matcher m = java.util.regex.Pattern.compile("\\((\\d+)\\)").matcher(label);
        if (m.find()) return m.group(1);
        // 回退：在当前语言环境的数组中查找完全匹配的位置
        try {
            String[] arr = getResources().getStringArray(R.array.wave_type_options);
            for (int i = 0; i < arr.length; i++) {
                if (label.equals(arr[i])) return String.valueOf(i + 1);
            }
        } catch (Exception ignored) {}
        return "0";
    }

    private String getText(View view, int id) {
        EditText input = view.findViewById(id);
        return input.getText().toString().trim();
    }

    @Override
    public void onRefresh() {
        super.onRefresh();
    }

    @Override
    protected void updateMeshMessage(final MeshMessage meshMessage) {
        super.updateMeshMessage(meshMessage);

        if (meshMessage instanceof VendorModelMessageStatus) {
            final VendorModelMessageStatus status = (VendorModelMessageStatus) meshMessage;
            final int opcode = status.getOpCode();
            final byte[] params = status.getParameters();

            if (opcode == 0xC102E5) {
                // 1. 解析 JSON 数据
                final String json = new String(params, StandardCharsets.UTF_8);
                Log.d("MeshMessage", "收到 C1 指令 JSON: " + json);

                try {
                    DeviceStatus deviceStatus = new Gson().fromJson(json, DeviceStatus.class);
                    if (deviceStatus != null) {
                        runOnUiThread(() -> {
                            tvOnOff.setText("开关: " + (deviceStatus.onoff == 1 ? "开" : "关"));
                            tvVoltage0.setText("电压0: " + deviceStatus.voltage0 + "V");
                            tvVoltage1.setText("电压1: " + deviceStatus.voltage1 + "V");
                            tvCurrent.setText("电流: " + deviceStatus.current + "A");
                            tvResistance.setText("阻抗: " + deviceStatus.resistance + "Ω");
                            tvSoc.setText("电量: " + deviceStatus.soc + "%");
                            tvGear.setText("档位: " + deviceStatus.gear);
                        });
                    }
                } catch (Exception e) {
                    Log.e("MeshMessage", "JSON 解析失败: " + e.getMessage());
                }

            } else if (opcode == 0xC202E5) {
                // 2. 处理其他指令
                Log.d("MeshMessage", "收到 C2 响应");
            }

        } else if (meshMessage instanceof ConfigVendorModelAppList) {
            final ConfigVendorModelAppList status = (ConfigVendorModelAppList) meshMessage;
            mViewModel.removeMessage();
            if (status.isSuccessful()) {
                if (handleStatuses()) return;
            } else {
                displayStatusDialogFragment(getString(R.string.title_vendor_model_app_list), status.getStatusCodeName());
            }

        } else if (meshMessage instanceof ConfigVendorModelSubscriptionList) {
            final ConfigVendorModelSubscriptionList status = (ConfigVendorModelSubscriptionList) meshMessage;
            mViewModel.removeMessage();
            if (status.isSuccessful()) {
                if (handleStatuses()) return;
            } else {
                displayStatusDialogFragment(getString(R.string.title_vendor_model_subscription_list), status.getStatusCodeName());
            }
        }

        hideProgressBar();
    }


    /**
     * Validate opcode
     *
     * @param opCode       opcode
     * @param opCodeLayout op c0de view
     * @return true if success or false otherwise
     */
    private boolean validateOpcode(final String opCode, final TextInputLayout opCodeLayout) {
        try {
            if (TextUtils.isEmpty(opCode)) {
                opCodeLayout.setError(getString(R.string.error_empty_value));
                return false;
            }

            if (opCode.length() % 2 != 0 || !opCode.matches(Utils.HEX_PATTERN)) {
                opCodeLayout.setError(getString(R.string.invalid_hex_value));
                return false;
            }
            if (MeshParserUtils.isValidOpcode(Integer.valueOf(opCode, 16))) {
                return true;
            }
        } catch (NumberFormatException ex) {
            opCodeLayout.setError(getString(R.string.invalid_value));
            return false;
        } catch (IllegalArgumentException ex) {
            opCodeLayout.setError(ex.getMessage());
            return false;
        } catch (Exception ex) {
            opCodeLayout.setError(ex.getMessage());
            return false;
        }
        return true;
    }

    /**
     * Validate parameters
     *
     * @param parameters       parameters
     * @param parametersLayout parameter view
     * @return true if success or false otherwise
     */
    private boolean validateParameters(final String parameters, final TextInputLayout parametersLayout) {
        try {
            if (TextUtils.isEmpty(parameters) && parameters.length() == 0) {
                return true;
            }

            if (parameters.length() % 2 != 0 || !parameters.matches(Utils.HEX_PATTERN)) {
                parametersLayout.setError(getString(R.string.invalid_hex_value));
                return false;
            }

            if (MeshParserUtils.isValidParameters(MeshParserUtils.toByteArray(parameters))) {
                return true;
            }
        } catch (NumberFormatException ex) {
            parametersLayout.setError(getString(R.string.invalid_value));
            return false;
        } catch (IllegalArgumentException ex) {
            parametersLayout.setError(ex.getMessage());
            return false;
        } catch (Exception ex) {
            parametersLayout.setError(ex.getMessage());
            return false;
        }
        return true;
    }

    /**
     * Send vendor model acknowledged message
     *
     * @param opcode     opcode of the message
     * @param parameters parameters of the message
     */
    public void sendVendorModelMessage(final int opcode, final byte[] parameters, final boolean acknowledged) {
        // 1、element address
        final Element element = mViewModel.getSelectedElement().getValue();
        if (element != null) {
            final VendorModel model = (VendorModel) mViewModel.getSelectedModel().getValue();
            if (model != null) {
                // appkey
                final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
                final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
                if (acknowledged) {
                    sendAcknowledgedMessage(element.getElementAddress(),
                            new VendorModelMessageAcked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters));
                } else {
                    sendUnacknowledgedMessage(element.getElementAddress(),
                            new VendorModelMessageAcked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters));
                }
            }
        }
    }
}
